package edu.bu.cs673.superkids123.children.controller.games;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;

import edu.bu.cs673.superkids123.AbstractFrame;
import edu.bu.cs673.superkids123.children.DataObjectAccess.LessonGameManager;
import edu.bu.cs673.superkids123.children.controller.AbstractGameController;
import edu.bu.cs673.superkids123.children.model.Game;
import edu.bu.cs673.superkids123.children.model.resources.AudioPlayer;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResource;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResourceProvider;
import edu.bu.cs673.superkids123.children.view.games.GameResultsView;
import edu.bu.cs673.superkids123.children.view.games.SubtractionGameView;


/**
 * 
 * SubtractionGameController
 * 
 * The MVC pattern is used for the Subtraction game. This is the
 * controller class for the subtraction game.
 * 
 * @author David Bardwell
 *
 */
public class SubtractionGameController extends AbstractGameController {
	
	private static final int POINTS_PER_QUESTION = 20;
	private int currentQuestion = 1;
	private Map<Integer, int[]> subtractionQuestionMap;
	private Map<Integer, int[]> numberChoicesMap;
	private Map<Integer, Integer> correctNumberAnswerMap;
	ChildrenResourceProvider provider = ChildrenResourceProvider.getInstance();
	private GameResultsController resultsController;
	private boolean isBusy = false;
	private boolean correctFirstTry = true;
	

	/**
	 * Constructor
	 * @param mainFrame
	 */
	public SubtractionGameController(AbstractFrame mainFrame) {
		super(mainFrame);
		resultsController = getMainFrame().getController( GameResultsController.class );
		populateSubtractionQuestionsAndAnswers();
		currentQuestion = 1;
	}
	
	/**
	 * startGame
	 * This is the entry point from the activities menu to start a new
	 * subtraction game.
	 */
	public void startGame() {
		resultsController.notifyResultsController("Subtraction Game");
		
		// Start Stat Recording
		List<Game> games = LessonGameManager.getAllActiveGames();
		for (Game game : games) {
			if (game.getName().contains("Subtraction"))
				start(game);
		}
		getMainFrame().changeView(SubtractionGameView.class);
	}
	
	/**
	 * Ends the game and saves the result.
	 * pass true if entire game was completed
	 * pass false if game is only partially complete, records in db at "Incomplete"
	 * @param complete
	 */
	public void endGame(boolean complete) {
       	if (isActive()) {
       		int score = resultsController.getCorrect() * POINTS_PER_QUESTION;
       		stop(complete, score);
       	}
       	if (complete) {
       		getMainFrame().getController(GameResultsController.class)
       			.showResultsScreen(this.getEarnedAchievements());
       	}
	}
	
	public void resetForNextGame() {
		currentQuestion = 1;
	}
	
	public int getCurrentQuestionNumber() {
		return currentQuestion;
	}
	
	public int[] getNextSubtractionQuestion() {
		return subtractionQuestionMap.get(currentQuestion);
	}
	
	public int[] getNextSubtractionAnswers() {
		return numberChoicesMap.get(currentQuestion);
	}
	
	public int getCorrectAnswer() {
		return correctNumberAnswerMap.get(currentQuestion);
	}
	
	public ImageIcon getImageForNumber(int number, float scaleValue) {
		return provider.getScaledImageByNumber(number, scaleValue);
	}
	
	public void playAudioMinus() {
		AudioPlayer audioPlayer = new AudioPlayer();
		byte[] audioData = provider.getAudioContent("audioMinus"); 
		audioPlayer.playAudio(audioData);
		try {
			Thread.sleep(100);
		}
		catch (InterruptedException ie) {
			System.out.println("Thread interrupted");
		}
	}
	
	public void playAudioEquals() {
		AudioPlayer audioPlayer = new AudioPlayer();
		byte[] audioData = provider.getAudioContent("audioEquals"); 
		audioPlayer.playAudio(audioData);
		try {
			Thread.sleep(100);
		}
		catch (InterruptedException ie) {
			System.out.println("Thread interrupted");
		}
	}
	
	public void answerButtonPressed(SubtractionGameView view, int buttonIndex) {
		if (isBusy) 
			return;
		
		isBusy = true;
		processSelection(view, buttonIndex);
	}
	
	/**
	 *  Process the selected answer from the child. Advance to the next question
	 *  or end of game summary screen if answer is correct. Stay on current question
	 *  if answer given is wrong asking the child to try again.
	 * @param view
	 * @param buttonIndex
	 */
	public void processSelection(SubtractionGameView view, int buttonIndex) {
		final SubtractionGameView view2 = view;
		final int buttonIndex2 = buttonIndex;
	
		Thread processSelectionThread = new Thread() {
			public void run() {
				int correctAnswer = 0;
			    correctAnswer = getCorrectAnswer();
				AudioPlayer audioPlayer = new AudioPlayer();
				
				if (buttonIndex2 == correctAnswer) {
					if (correctFirstTry == true) {
					    resultsController.correct++;
					}    
					else correctFirstTry = true;
					
					view2.updateMessage("Correct - Very Good!");
					byte[] audioData = provider.getAudioContent(ChildrenResource.audioCorrect); 
					audioPlayer.playAudio(audioData);
					try {
						Thread.sleep(100);
					}
					catch (InterruptedException ie) {
						System.out.println("Thread interrupted");
					}
				    view2.updateMessage("Select the correct answer");
				    currentQuestion++;
				    if (currentQuestion <= 5) {
					    view2.displayNextQuestionAndAnswers(
					    		currentQuestion,
					    		getNextSubtractionQuestion(),
					    		getNextSubtractionAnswers());
				    }
				    else {
				    	// go to the game results screen and save results to database
				    	isBusy = false;
				    	endGame(true);
				    }
				}
				else {
					correctFirstTry = false;
					view2.updateMessage("Sorry, try again.");
					byte[] audioData = provider.getAudioContent(ChildrenResource.audioTryAgain); 
					audioPlayer.playAudio(audioData);
					try {
						Thread.sleep(100);
					}
					catch (InterruptedException ie) {
						System.out.println("Thread interrupted");
					}
					
					view2.updateMessage("Select the correct answer");
				}
				isBusy = false;
			}
		};
		processSelectionThread.start();
	} 
	
	// load the game questions and answers which will be the same each time
	private void populateSubtractionQuestionsAndAnswers() {
		subtractionQuestionMap = new HashMap<Integer, int[]>();
		subtractionQuestionMap.put(1, new int[] {10, 5});
		subtractionQuestionMap.put(2, new int[] {8, 3});
		subtractionQuestionMap.put(3, new int[] {3, 2});
		subtractionQuestionMap.put(4, new int[] {4, 2});
		subtractionQuestionMap.put(5, new int[] {5, 3});
		
		numberChoicesMap = new HashMap<Integer, int[]>();
		numberChoicesMap.put(1, new int[] {6, 5, 4, 3});
		numberChoicesMap.put(2, new int[] {7, 6, 5, 4});
		numberChoicesMap.put(3, new int[] {4, 3, 2, 1});
		numberChoicesMap.put(4, new int[] {7, 5, 3, 2});
		numberChoicesMap.put(5, new int[] {2, 3, 4, 5});
		
		correctNumberAnswerMap = new HashMap<Integer, Integer>();
		correctNumberAnswerMap.put(1, 1);
		correctNumberAnswerMap.put(2, 2);
		correctNumberAnswerMap.put(3, 3);
		correctNumberAnswerMap.put(4, 3);
		correctNumberAnswerMap.put(5, 0);
	}
}
